package org.pay.service.impl;

import org.pay.service.BaseService;
import org.springframework.stereotype.Service;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.pay.core.common.constant.MchConstant;
import org.pay.core.common.domain.BaseParam;
import org.pay.core.common.enumm.RetEnum;
import org.pay.core.common.util.*;
import org.pay.service.dao.mapper.MchAccountMapper;
import org.pay.service.dao.mapper.MchInfoMapper;
import org.pay.core.entity.MchAccount;
import org.pay.core.entity.MchInfo;
import org.pay.core.service.IMchInfoService;
import org.pay.core.entity.MchInfoExample;

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author: yangshancheng
 * @date: 17/9/8
 * @description:
 */
@Service
public class MchInfoServiceImpl extends BaseService implements IMchInfoService {

    private static final MyLog _log = MyLog.getLog(MchInfoServiceImpl.class);

    @Autowired
    private MchInfoMapper mchInfoMapper;

    @Autowired
    private MchAccountMapper mchAccountMapper;

    @Override
    public Map selectMchInfo(String jsonParam) {
        BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
        Map<String, Object> bizParamMap = baseParam.getBizParamMap();
        if (ObjectValidUtil.isInvalid(bizParamMap)) {
            _log.warn("查询商户信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
            return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
        }
        Long mchId = baseParam.isNullValue("mchId") ? null : Long.parseLong(bizParamMap.get("mchId").toString());
        if (ObjectValidUtil.isInvalid(mchId)) {
            _log.warn("查询商户信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
            return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
        }
        MchInfo mchInfo = super.baseSelectMchInfo(mchId);
        if(mchInfo == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
        String jsonResult = JsonUtil.object2Json(mchInfo);
        return RpcUtil.createBizResult(baseParam, jsonResult);
    }

    @Override
    public int addMchInfo(MchInfo record) {
        return addMchInfo4Transactional(record);
    }

    @Override
    public int register(MchInfo record) {
        return mchInfoMapper.insertSelective(record);
    }

    @Override
    public int update(MchInfo record) {
        return mchInfoMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public MchInfo findByMchId(Long mchId) {
        return mchInfoMapper.selectByPrimaryKey(mchId);
    }

    @Override
    public MchInfo findByLoginName(String loginName) {
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        if(StrUtil.checkEmail(loginName)) {
            criteria.andEmailEqualTo(loginName);
        }else if(StrUtil.checkMobileNumber(loginName)) {
            criteria.andMobileEqualTo(Long.parseLong(loginName));
        }else if(NumberUtils.isDigits(loginName)) {
            criteria.andMchIdEqualTo(Long.parseLong(loginName));
        }else {
            return null;
        }
        List<MchInfo> mchInfoList = mchInfoMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(mchInfoList)) return null;
        return mchInfoList.get(0);
    }

    @Override
    public MchInfo findByMobile(Long mobile) {
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        criteria.andMobileEqualTo(mobile);
        List<MchInfo> mchInfoList = mchInfoMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(mchInfoList)) return null;
        return mchInfoList.get(0);
    }

    @Override
    public MchInfo findByEmail(String email) {
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        criteria.andEmailEqualTo(email);
        List<MchInfo> mchInfoList = mchInfoMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(mchInfoList)) return null;
        return mchInfoList.get(0);
    }

    @Override
    public int auditOk(Long mchInd) {
        // 修改商户状态
        MchInfo updateMchInfo = new MchInfo();
        updateMchInfo.setState(MchConstant.STATUS_OK);
        updateMchInfo.setRole(MchConstant.MCH_ROLE_NORMAL);
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        criteria.andMchIdEqualTo(mchInd);
        List<Byte> status = new LinkedList<>();
        status.add(MchConstant.STATUS_AUDIT_ING);
        status.add(MchConstant.STATUS_AUDIT_NOT);
        criteria.andStatusIn(status);
        int count = mchInfoMapper.updateByExampleSelective(updateMchInfo, example);
        if(count == 1) {
            MchInfo mchInfo = findByMchId(mchInd);
            // 插入商户账户信息
            MchAccount mchAccount = new MchAccount();
            mchAccount.setMchId(mchInfo.getMchId());
            mchAccount.setName(mchInfo.getName());
            mchAccount.setKind(mchInfo.getKind());
            mchAccount.setBalance(BigDecimal.ZERO.longValue());
            mchAccount.setSecurityMoney(BigDecimal.ZERO.longValue());
            mchAccount.setSettAmount(BigDecimal.ZERO.longValue());
            mchAccount.setUnBalance(BigDecimal.ZERO.longValue());
            mchAccount.setTodayExpend(BigDecimal.ZERO.longValue());
            mchAccount.setTodayIncome(BigDecimal.ZERO.longValue());
            mchAccount.setTotalExpend(BigDecimal.ZERO.longValue());
            mchAccount.setTotalIncome(BigDecimal.ZERO.longValue());
            count = mchAccountMapper.insertSelective(mchAccount);
        }
        return count;
    }

    @Override
    public int auditNot(Long mchInd) {
        MchInfo mchInfo = new MchInfo();
        mchInfo.setState(MchConstant.STATUS_AUDIT_NOT);
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        criteria.andMchIdEqualTo(mchInd);
        criteria.andStatusEqualTo(MchConstant.STATUS_AUDIT_ING);
        int count = mchInfoMapper.updateByExampleSelective(mchInfo, example);
        return count;
    }

    @Override
    public List<MchInfo> select(int offset, int limit, MchInfo mchInfo) {
        MchInfoExample example = new MchInfoExample();
        example.setOrderByClause("create_time DESC");
        example.setOffset(offset);
        example.setLimit(limit);
        MchInfoExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchInfo);
        return mchInfoMapper.selectByExample(example);
    }

    @Override
    public List<MchInfo> select4Audit(int offset, int limit, MchInfo mchInfo) {
        MchInfoExample example = new MchInfoExample();
        example.setOrderByClause("create_time DESC");
        example.setOffset(offset);
        example.setLimit(limit);
        MchInfoExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchInfo);
        List<Byte> status = new LinkedList<>();
        status.add(MchConstant.STATUS_AUDIT_NOT);
        status.add(MchConstant.STATUS_AUDIT_ING);
        criteria.andStatusIn(status);
        return mchInfoMapper.selectByExample(example);
    }

    @Override
    public List<MchInfo> select4Normal(int offset, int limit, MchInfo mchInfo) {
        MchInfoExample example = new MchInfoExample();
        example.setOrderByClause("create_time DESC");
        example.setOffset(offset);
        example.setLimit(limit);
        MchInfoExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchInfo);
        List<Byte> status = new LinkedList<>();
        status.add(MchConstant.STATUS_STOP);
        status.add(MchConstant.STATUS_OK);
        criteria.andStatusIn(status);
        return mchInfoMapper.selectByExample(example);
    }

    @Override
    public Integer count(MchInfo mchInfo) {
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchInfo);
        return mchInfoMapper.countByExample(example);
    }

    @Override
    public Integer count4Audit(MchInfo mchInfo) {
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchInfo);
        List<Byte> status = new LinkedList<>();
        status.add(MchConstant.STATUS_AUDIT_NOT);
        status.add(MchConstant.STATUS_AUDIT_ING);
        criteria.andStatusIn(status);
        return mchInfoMapper.countByExample(example);
    }

    @Override
    public Integer count4Normal(MchInfo mchInfo) {
        MchInfoExample example = new MchInfoExample();
        MchInfoExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchInfo);
        List<Byte> status = new LinkedList<>();
        status.add(MchConstant.STATUS_STOP);
        status.add(MchConstant.STATUS_OK);
        criteria.andStatusIn(status);
        return mchInfoMapper.countByExample(example);
    }

    void setCriteria(MchInfoExample.Criteria criteria, MchInfo mchInfo) {
        if(mchInfo != null) {
            if(mchInfo.getMchId() != null) criteria.andMchIdEqualTo(mchInfo.getMchId());
            if(mchInfo.getKind() != null && mchInfo.getKind().byteValue() != -99) criteria.andTypeEqualTo(mchInfo.getKind());
            if(mchInfo.getEmail() != null) criteria.andEmailEqualTo(mchInfo.getEmail());
            if(mchInfo.getMobile() != null) criteria.andMobileEqualTo(mchInfo.getMobile());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    int addMchInfo4Transactional(MchInfo mchInfo) {
        // 插入商户基本信息
        mchInfoMapper.insertSelective(mchInfo);
        // 插入商户账户信息
        MchAccount mchAccount = new MchAccount();
        mchAccount.setMchId(mchInfo.getMchId());
        mchAccount.setName(mchInfo.getName());
        mchAccount.setKind(mchInfo.getKind());
        mchAccount.setBalance(BigDecimal.ZERO.longValue());
        mchAccount.setSecurityMoney(BigDecimal.ZERO.longValue());
        mchAccount.setSettAmount(BigDecimal.ZERO.longValue());
        mchAccount.setUnBalance(BigDecimal.ZERO.longValue());
        mchAccount.setTodayExpend(BigDecimal.ZERO.longValue());
        mchAccount.setTodayIncome(BigDecimal.ZERO.longValue());
        mchAccount.setTotalExpend(BigDecimal.ZERO.longValue());
        mchAccount.setTotalIncome(BigDecimal.ZERO.longValue());
        int count = mchAccountMapper.insertSelective(mchAccount);
        return count;
    }

}
